<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    <title>Capturing HTTP communications</title>
    <link rel="stylesheet" type="text/css" href="../css/common.css" />
    <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" />
    <link rel="stylesheet" type="text/css" href="../css/prettify.css" media="screen" />

  </head>
  <body onload="prettyPrint()">
    <script type="text/javascript">prefix='../';</script>
    <script type="text/javascript" src="../js/prettify.js"></script>
    <script src="../templates/header.js" type="text/javascript"></script>
    <div id="left">
      <noscript>Please turn on Javascript to view this menu</noscript>
      <script src="../templates/left.js" type="text/javascript"></script>
    </div>
    <div id="content">
      
      <h2>Capturing incoming HTTP requests and outgoing responses</h2>

      <p>Logback ships with a module called logback-access which
      integrates with Servlet containers such as Jetty or Tomcat to
      provide rich and powerful HTTP-access log functionality.
      </p>

      <p>When diagnosing issues in a web-application, it is very
      helpful to be able to capture incoming HTTP requests and the
      outgoing response. This is particularly true for a
      web-applications offering web-services using <a
      href="http://en.wikipedia.org/wiki/SOAP">SOAP</a>. Having access
      to the "raw" SOAP message makes it much easier to diagnose
      errors caused by misspelled namespaces or missing fields.
      </p>

      <p>Certain Web-Service stacks can be easily configured to log
      SOAP traffic. For instance, with JBoss' Web-services stack, you
      can set the level of the
      <code>org.jboss.ws.core.MessageTrace</code> logger to
      <code>TRACE</code> in order to enable SOAP message tracing as <a
      href="http://community.jboss.org/wiki/JBossWS-Log4j">documented
      in the Jboss wiki</a>.
      </p>

      <p>If you are using a different Web-Services stack, e.g. Metro,
      it might not be very convenient to enable SOAP message
      tracing. In that case, and assuming your application is deployed
      on Tomcat, you might want to enable <a
      href="http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#Request_Dumper_Filter">RequestDumperFilter</a>.
      Unfortunately, not only is <code>RequestDumperFilter</code>
      rather hard to install, it does not dump the payload of the
      incoming request nor the outgoing response.
      </p>

      <p>With the help of <a href="../access.html#teeFilter">
      logback-access its TeeFilter</a> you can capture the full input
      and output for each request as explained below.
  
      </p>

      <h3><a name="capturing" href="#capturing">Capturing</a></h3>

      <p>The <code>TeeFilter</code>, as any other servlet filter,
      needs to be declared in your web-application's <em>web.xml</em>
      file. Here is the declaration to add to your web-application's
      <em>web.xml</em> file.
      </p>

    <pre class="prettyprint source">&lt;filter&gt;
  &lt;filter-name&gt;TeeFilter&lt;/filter-name&gt;
  &lt;filter-class&gt;ch.qos.logback.access.servlet.TeeFilter&lt;/filter-class&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
  &lt;filter-name&gt;TeeFilter&lt;/filter-name&gt;
  &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</pre>

      <p>The <code>TeeFilter</code> requires the logback-access module
      to be installed in your web-server. The installation of
      logback-access is explained <a
      href="../access.html">elsewhere</a>. Once you have installed
      logback-access into your Servlet container, e.g. Tomcat or
      Jetty, you can configure logback-access according to your wishes
      with the help of a configuration file named
      <em>logback-access.xml</em>.
      </p>
      
      <p>Here is a sample <em>logback-access.xml</em> configuration
      file which will output the full contents of the request and
      response on the console.
      </p>

  <pre class="prettyprint source">&lt;configuration&gt;
  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"&gt;
    &lt;encoder&gt;      
      &lt;pattern&gt;<b>%fullRequest</b>%n%n<b>%fullResponse</b>&lt;/pattern&gt;
    &lt;/encoder&gt;
  &lt;/appender&gt;
	
  &lt;appender-ref ref="STDOUT" /&gt;
&lt;/configuration&gt;</pre>
      
     <p>For the list of conversion words supported by logback-access'
     <code>PatternLayout</code> please refer to <a
     href="manual/layouts.html#AccessPatternLayout">its documentation</a>.
     </p>

     <p>Here is the output generated when accessing the <a
     href="../demo.html">logback-demo</a> application configured as shown
     above, yields:</p>

     <p class="source"><b>GET /logback-demo/index.jsp HTTP/1.1</b>
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20070312 Firefox/1.5.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8080/logback-demo/login.jsp
Cookie: JSESSIONID=15c7tqi9ehlwk;  OID324nkzcmr=null; OID32862zgoa=null; 



<b>HTTP/1.1 200 OK</b>
Content-Type: text/html; charset=iso-8859-1
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONID=bgebt99ce9om;path=/logback-demo


&lt;html&gt;
&lt;head&gt;
        &lt;LINK REL=StyleSheet HREF="css/pk.css" /&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;h2&gt;Logback demo center&lt;/h2&gt;

[snip, so that text is reasonably sized]</p>

<p>&nbsp;</p>

      <h3><a name="disabling" href="#disabling">Disabling
      <code>TeeFilter</code> in the production environment</a></h3>

      <p>Due to its intrusive nature, <code>TeeFilter</code> can slow
      down performance. Moreover, although we have fixed all currently
      known bugs, <code>TeeFilter</code> has broken otherwise
      correctly behaving applications in the past. Thus, while
      extremely useful during problem hunting, we do not recommend
      having <code>TeeFilter</code> active in production systems. In
      order to avoid shipping different code for test and production
      environments, <code>TeeFilter</code> supports includes and
      excludes parameters. <code>TeeFilter</code> will be active if
      the current host is listed in the includes list and absent in
      the excludes list. By special convention, an empty
      <em>includes</em> list is interpreted as to contain all possible
      host names in the universe.
      </p>
      
      <p>Assume we wish to capture HTTP traffic on all hosts except on
      orion and gemini, the hostnames of the the production systems,
      we would write:</p>

        <pre class="prettyprint source">&lt;filter>
  &lt;filter-name>TeeFilter&lt;/filter-name>
  &lt;filter-class>ch.qos.logback.access.servlet.TeeFilter&lt;/filter-class>
  &lt;init-param>
    <b>&lt;!-- exclude captures on production systems --></b>
    &lt;param-name><b>excludes</b>&lt;/param-name>
    &lt;param-value>orion, gemini&lt;/param-value>
  &lt;/init-param>
&lt;/filter>  </pre>
  
      <p>If it is easier to explicitly name the integration machines,
      you could list them in the includes list and omit the excludes
      list.
      </p>

      <h3><a name="filtering" href="#filtering">Filtering captured
      requests</a></h3>

      <p>Let assume that our web-application is deployed in a
      cluster. The cluster is located behind a load-balancer which
      probes each member of the cluster once or twice a second to
      check whether it is alive. Whenever a member becomes unavailable
      the load-balancer will immediately (well, after at most one
      second) divert traffic from that member.
      </p>

      <p>While such a load-balancing strategy will ensure
      high-availability of your web-application, it will also
      seriously pollute the access-logs with the contents of each
      probe made by the load-balancer.
      </p>

      <p>We need to a way to filter-out these probes so that they no
      longer contaminate the log output. In other words, we need to
      distinguish probes emanating from the load-balancer from other
      requests. The contents of the probes can give us clues about
      possible distinguishing criteria.</p>

      <p>Here is a sample probe as logged by logback-access:</p>

      <pre class="source"><b>HEAD</b> /myapp/<b>probe</b> HTTP/1.1
connection: Close
host: 192.168.1.1

HTTP/1.1 200 OK
Expires: Thu, 01 Jan 1970 01:00:00 CET
X-Powered-By: Servlet 2.4;
Cache-Control: no-cache
Pragma: No-cache </pre>

      <p>From the above, we can see that the load-balancer probes
      employ the <a
      href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4">HTTP
      HEAD method</a> instead of the usual GET or POST. We can also
      see that the request URI for the probes contains the string
      "probe".</p>

      <p>Here is a <em>logback-access.xml</em> configuration file
      which will deny any <code>AccessEvent</code> where the method is
      HEAD. Note that events are evaluated using
      <code>JaninoEventEvaluator</code> which requires Janino.</p>

      <pre class="prettyprint source">&lt;configuration>
  &lt;!-- always a good idea to install OnConsoleStatusListener -->
  &lt;statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    &lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;!-- in the absence of a class attribute the &lt;evaluator> element 
           defaults to ch.qos.logback.access.boolex.JaninoEventEvaluator --&gt;
      &lt;evaluator>
        &lt;expression><b>event.getMethod().equals("HEAD")</b>&lt;/expression>
      &lt;/evaluator>
      &lt;onMismatch>NEUTRAL&lt;/onMismatch>
      &lt;onMatch>DENY&lt;/onMatch>
    &lt;/filter>

    &lt;encoder>
      &lt;pattern>%fullRequest%n%n%fullResponse&lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;appender-ref ref="STDOUT" />
&lt;/configuration> </pre>
      
      <script src="../templates/footer.js" type="text/javascript"></script>	
    </div>
  </body>
</html>
 